[Solana] Wallet情報をrecoverする
Introduction
Solanaとは、スマートコントラクト機能を備えた
パブリックブロックチェーンプラットフォームです(暗号通貨はSOL)。
ライブラリもいろいろ提供されており、
プログラムから情報を取得したり暗号資産の送受信もできます。
そういったシステムの特性上、Wallet/鍵の管理は重要です。
今回はプログラムからWalletにアクセスする方法について紹介します。
Wallet & Keypair
SolanaでSOLトークンを受信できるようにする場合、
Wallet(ウォレット)を作成する必要があります。
一般的にWalletは、暗号資産の所有権を管理するためのデバイスまたはアプリケーションです。
このWalletは特殊なハードウェアだったりコンピュータのファイルだったりします。
これとか。
Keypairは、(solana-keygenコマンドとかで)生成された秘密鍵とその暗号化された公開鍵です。
公開鍵(pubkey)は、Walletのアドレスとして使用します。
このアドレスは共有しても問題ありません。
(暗号資産の送受信に必要)
ブロックチェーンによってはアドレス情報からWallet情報を取得可能です。
※Wallet情報の変更やトークン引き出しは不可
秘密鍵は、暗号通貨の送信やWallet情報の変更するための署名に必要となります。
公開鍵と違い、秘密鍵は絶対に共有してはいけません。
秘密鍵が漏洩すると、トークン全部持っていかれます。
また、秘密鍵を紛失した場合は
そのアドレスのトークンが永久に失われるので取り扱いに注意しましょう。
mnemonic
他のブロックチェーンではシークレットリカバリフレーズとか
シードフレーズとよばれることもあります。
これはWalletアプリ自体を復元するためのキーワードです。
試しに、Solana CLIをつかって確認してみましょう。
% solana-keygen new --no-outfile Generating a new keypair For added security, enter a BIP39 passphrase NOTE! This passphrase improves security of the recovery seed phrase NOT the keypair file itself, which is stored as insecure plain text BIP39 Passphrase (empty for none): ====================================================================== pubkey: XXXXXXXXXXXXXXXXXXXXXXXX ====================================================================== Save this seed phrase and your BIP39 passphrase to recover your new keypair: ribbon grant banner error ahead pole vital top real feel tomato duck ======================================================================
solana-keygen newで新しいキーペアを作成しています。
公開鍵とmnemonic(ribbonとかgrantとかの12の単語)が表示されてます。
ちなみに、--language japaneseオプションをつけると日本語のmnemonicが生成されます。
では、プログラムからWalletやKeypair情報にアクセスしてみます。
Environment
- OS : MacOS 12.4
- Node : v18.2.0
- yarn : 1.22.15
Setup
Solana CLI toolのインストールをします。
% sh -c "$(curl -sSfL https://release.solana.com/v1.10.26/install)" %solana --version solana-cli 1.10.25 (src:d64f6808; feat:965221688)
Try
まずはサンプルとなるキーペアを生成。
% solana-keygen new --no-bip39-passphrase -o ./test-walllet.json Generating a new keypair Wrote new keypair to ./test-walllet.json =========================================================================== pubkey: <公開鍵> =========================================================================== Save this seed phrase and your BIP39 passphrase to recover your new keypair: < mnemonic > ===========================================================================
CLIでmnemonicから復元するには↓のコマンドを実行し、mnemonicを入力すれば復元可能です。
% solana-keygen recover 'prompt://?key=0/0' -o ./test-wallet-recover.json [recover] seed phrase:
TypeScriptでKeypairのrecover
次はTypescriptでmnemonicやSecretKeyからKeypairを復元してみます。
まずは必要パッケージのインストールをします。
% yarn add @solana/web3.js bip39 bs58 @solana/wallet-adapter-wallets @solana/wallet-adapter-base ed25519-hd-key
そして確認用プログラム。npx ts-node test.tsで実行できます。
//test.ts import { Keypair } from "@solana/web3.js"; import * as bip39 from "bip39"; import * as bs58 from "bs58"; import { derivePath } from "ed25519-hd-key"; import assert from "assert"; const derivePathStr = "m/44'/501'/0'/0'"; ///////////////////////////////////////////////////////// // these words is very important. do not share!!!!!! ///////////////////////////////////////////////////////// //wallet アドレス。公開鍵 const address = '<public key>'; //秘密鍵(phantomの秘密鍵エクスポートで出せたりする) const secret_key = '<secret key>'; //mnemonic const mnemonic ="<secret recovery phrase>"; ///////////////////////////////////////////////////////// function restore_from_mnemonic(mnemonic:string) : Keypair { const seed = bip39.mnemonicToSeedSync(mnemonic); const seedBuffer = Buffer.from(seed).toString('hex'); const derivedSeed = derivePath(derivePathStr, seedBuffer).key; const keypair = Keypair.fromSeed(derivedSeed); return keypair; } function restore_from_secret(secret_key:string) : Keypair { return Keypair.fromSecretKey(bs58.decode(secret_key)); } //秘密鍵からKeypair復元 const keypair_from_secret = restore_from_secret(secret_key); console.log(`from_secret.publicKey : ${keypair_from_secret.publicKey.toBase58()}`); console.log(`from_secret.secretKey : ${bs58.encode(keypair_from_secret.secretKey)}`); //mnemonicからKeypair復元 const keypair_from_mnemonic = restore_from_mnemonic(mnemonic); console.log(`from_mnemonic.publicKey : ${keypair_from_mnemonic.publicKey.toBase58()}`); console.log(`from_mnemonic.secretLey : ${bs58.encode(keypair_from_mnemonic.secretKey)}`); //assert assert(keypair_from_secret.publicKey.toBase58() == keypair_from_mnemonic.publicKey.toBase58()); assert(bs58.encode(keypair_from_secret.secretKey) == bs58.encode(keypair_from_mnemonic.secretKey)); assert(address == keypair_from_secret.publicKey.toBase58()); assert(secret_key == bs58.encode(keypair_from_secret.secretKey));
秘密鍵からKeypairを復元するにはKeypair.fromSecretKeyを使用。
mnemonicからの復元はmnemonicToSeedSync(非同期版のmnemonicToSeedもある)
を使います。